検証用のALBを作成するCloudFormationテンプレート
コンセプト
ALBの構築作業を行っているとALBの設定の検証を行いたい局面があると思います。
そんなとき毎回EC2立てて、ターゲットグループ作って、ALB作ってと作業をするのは冗長なのでCloudFormationテンプレート一つで簡単に構築できるようにしました。
本番で使うには色々と不足している部分もあるかと思いますが、検証に使う分にはミニマルで使いやすいのではないかと思います。
構成
本テンプレートで作成できる環境は以下のようなものです。
EC2は1台でパブリックサブネットに配置しています。 これはEC2にSessionManagerにNATゲートウェイなしで接続するためです。
EC2インスタンスではNginxが起動します。 EC2のOSはAmazonLinux2です。
テンプレート
AWSTemplateFormatVersion: '2010-09-09' Description: ALB and Nginx on EC2 Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 Tags: - Key: Name Value: !Sub ${AWS::StackName}-vpc PublicSubnet0: Type: AWS::EC2::Subnet DependsOn: AttachGateway Properties: VpcId: !Ref VPC AvailabilityZone: ap-northeast-1a CidrBlock: 10.0.0.0/24 Tags: - Key: Name Value: !Sub ${AWS::StackName}-public-1a-subnet PublicSubnet1: Type: AWS::EC2::Subnet DependsOn: AttachGateway Properties: VpcId: !Ref VPC AvailabilityZone: ap-northeast-1c CidrBlock: 10.0.1.0/24 Tags: - Key: Name Value: !Sub ${AWS::StackName}-public-1c-subnet InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: !Sub ${AWS::StackName}-igw AttachGateway: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref VPC InternetGatewayId: !Ref InternetGateway PublicRouteTable: Type: AWS::EC2::RouteTable DependsOn: AttachGateway Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub ${AWS::StackName}-public-rt PublicRoute: Type: AWS::EC2::Route DependsOn: AttachGateway Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway PublicSubnet0RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet0 RouteTableId: !Ref PublicRouteTable PublicSubnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1 RouteTableId: !Ref PublicRouteTable ALBSecurityGroup: Type: "AWS::EC2::SecurityGroup" Properties: GroupDescription: "ALB SG" GroupName: !Sub ${AWS::StackName}-alb-sg VpcId: !Ref VPC Tags: - Key: Name Value: !Sub ${AWS::StackName}-alb-sg SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 0.0.0.0/0 EC2SecurityGroup: Type: "AWS::EC2::SecurityGroup" Properties: GroupDescription: "EC2 SG" GroupName: !Sub ${AWS::StackName}-ec2-sg VpcId: !Ref VPC Tags: - Key: Name Value: !Sub ${AWS::StackName}-ec2-sg SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 SourceSecurityGroupId: !Ref ALBSecurityGroup EC2InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: "/" Roles: - !Ref EC2Role InstanceProfileName: !Sub ${AWS::StackName}-ec2-profile EC2Role: Type: "AWS::IAM::Role" Properties: Path: "/" RoleName: !Sub ${AWS::StackName}-ec2-role Tags: - Key: Name Value: !Sub ${AWS::StackName}-ec2-role AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: ec2.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" KeyPair: Type: 'AWS::EC2::KeyPair' Properties: KeyName: !Sub ${AWS::StackName}-keypair WebServer: Type: AWS::EC2::Instance Properties: Tags: - Key: Name Value: !Sub ${AWS::StackName}-web InstanceType: t3.nano BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeType: gp3 VolumeSize: 8 DeleteOnTermination: true Encrypted: true NetworkInterfaces: - AssociatePublicIpAddress: "true" DeviceIndex: "0" GroupSet: - !Ref EC2SecurityGroup SubnetId: !Ref PublicSubnet0 ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}' IamInstanceProfile: !Ref EC2InstanceProfile KeyName: !Ref KeyPair DisableApiTermination: false EbsOptimized: true UserData: Fn::Base64: | #!/bin/bash sudo amazon-linux-extras install nginx1 sudo systemctl enable nginx sudo systemctl start nginx ALB: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Type: "application" Scheme: "internet-facing" Name: !Sub ${AWS::StackName}-alb Tags: - Key: Name Value: !Sub ${AWS::StackName}-alb IpAddressType: ipv4 Subnets: - !Ref PublicSubnet0 - !Ref PublicSubnet1 SecurityGroups: - !Ref ALBSecurityGroup ListenerHTTP: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref TargetGroup LoadBalancerArn: !Ref ALB Port: 80 Protocol: HTTP TargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: Name: !Sub ${AWS::StackName}-tg Tags: - Key: Name Value: !Sub ${AWS::StackName}-tg Port: 80 Protocol: HTTP Matcher: HttpCode: '200' VpcId: !Ref VPC TargetType: instance Targets: - Id: !Ref WebServer Outputs: ALBURL: Description: ALB endpoint URL Value: !Join - "" - - http:// - !GetAtt ALB.DNSName
使い方
デプロイ
今回はテンプレートにパラメータは設定していないので、そのままスタック名だけ決めてデプロイすれば問題ありません。
デプロイ途中で以下のような警告が表示されると思いますが、これはSessionManagerでEC2にアクセスする用のIAMロールを作成しているためです。 スタックの作成が完了すると「{スタック名}-xxx」といった感じでリソースが作成されます。
ALBへのアクセス
スタックの出力にALBのURLが表示されているのでここにアクセスすればNginxにアクセス可能です。
正しくデプロイされていれば以下のようなページが表示されるはずです。
今回はACMなどのリソースあとで作るものとし、HTTPS用のリスナーは定義していません。(セキュリティグループは開けてあります)
削除
ALBやEC2の削除保護は無効にしてあるのでスタックを削除すれば同じく削除されます。
EC2への接続
今回はEC2へのアクセスはセッションマネージャーの利用を想定し、それ用のロールも付与してあります。
もし、SSHなどで直接アクセスしたい場合はパラメータストアにキーペアが保存してあるのでそこから取得可能です。 パラメータストアを確認すると「/ec2/keypair/key-xxx」といったパラメータが作成されてます。 こちらのキーペアをコピペしてファイルに貼り付ければ利用可能です。
最後に
これで検証を行う際すぐにALBを用意できるようになりました。 作ったり消したりしながらALBの検証を行っていきたいと思います。